"""
AI虚拟主播系统 - 主程序
整合所有模块,协调系统运行
"""

import asyncio
import signal
import sys
import threading
from pathlib import Path

from src.utils.config_manager import get_config
from src.utils.logger import get_logger
from src.core.models import DanmakuMessage
from src.core.message_queue import MessageQueue, MessageProcessor, ConcurrentController
from src.services.danmaku_listener import BilibiliDanmakuListener
from src.services.ai_engine import AIDialogueEngine, SensitiveWordFilter
from src.services.tts_engine import TTSEngine, AudioPlayer
from src.services.fish_audio_tts import FishAudioTTS
from src.services.chattts_engine import ChatTTSEngine
from src.services.minimax_tts import MiniMaxTTS
from src.services.volcengine_tts import VolcengineTTS
from src.services.live2d_renderer import Live2DRenderer


class AIVTuberSystem:
    """AI虚拟主播系统"""

    def __init__(self, config_path: str = None):
        """
        初始化系统
        
        Args:
            config_path: 配置文件路径
        """
        # 加载配置
        self.config = get_config(config_path)

        # 初始化日志
        logging_config = self.config.get('logging', {})
        self.logger = get_logger(
            level=logging_config.get('level', 'INFO'),
            log_to_file=logging_config.get('log_to_file', True),
            log_file=logging_config.get('log_file', './logs/ai_vtuber.log'),
            max_file_size=logging_config.get('max_file_size', 10485760),
            backup_count=logging_config.get('backup_count', 5)
        )

        self.logger.info("=" * 60)
        self.logger.info("AI虚拟主播系统启动中...")
        self.logger.info("=" * 60)

        # 验证配置
        if not self.config.validate():
            self.logger.critical("配置验证失败,请检查config.yaml和.env文件")
            sys.exit(1)

        # 核心组件
        self.message_queue: MessageQueue = None
        self.message_processor: MessageProcessor = None
        self.danmaku_listener: BilibiliDanmakuListener = None
        self.ai_engine: AIDialogueEngine = None
        self.tts_engine: TTSEngine = None
        self.live2d_renderer: Live2DRenderer = None
        self.audio_player: AudioPlayer = None
        self.sensitive_filter: SensitiveWordFilter = None

        # 并发控制
        self.controller = ConcurrentController()

        # 运行状态
        self.is_running = False

        # 初始化组件
        self._initialize_components()

    def _initialize_components(self):
        """初始化所有组件"""
        self.logger.info("正在初始化系统组件...")

        # 1. 消息队列
        system_config = self.config.get_system_config()
        self.message_queue = MessageQueue(
            max_size=system_config.get('message_queue_size', 100),
            max_messages_per_second=system_config.get('max_messages_per_second', 3),
            enable_priority=system_config.get('enable_priority_queue', True)
        )
        self.logger.info("✓ 消息队列初始化完成")

        # 2. AI对话引擎
        deepseek_config = self.config.get_deepseek_config()
        self.ai_engine = AIDialogueEngine(
            api_key=deepseek_config['api_key'],
            base_url=deepseek_config.get('base_url', 'https://api.deepseek.com'),
            model=deepseek_config.get('model', 'deepseek-chat'),
            system_prompt=self.config.get_system_prompt(),
            temperature=deepseek_config.get('temperature', 0.8),
            max_tokens=deepseek_config.get('max_tokens', 100),
            timeout=deepseek_config.get('timeout', 30),
            max_context_length=system_config.get('max_context_length', 10)
        )
        self.logger.info("✓ AI对话引擎初始化完成")

        # 3. 敏感词过滤器
        security_config = self.config.get('security', {})
        if security_config.get('enable_sensitive_word_filter', False):
            sensitive_words_file = security_config.get('sensitive_words_file')
            self.sensitive_filter = SensitiveWordFilter(sensitive_words_file)
        self.logger.info("✓ 敏感词过滤器初始化完成")

        # 4. TTS引擎
        tts_engine_type = self.config.get_tts_engine_type()
        self.logger.info(f"正在初始化TTS引擎: {tts_engine_type}")
        
        if tts_engine_type == "volcengine":
            # 使用火山引擎豆包TTS 2.0 (推荐 - 字节出品，价格便宜)
            tts_config = self.config.get_tts_config()
            app_id = tts_config.get('app_id', '')
            access_token = tts_config.get('access_token', '')
            
            if not app_id or not access_token:
                self.logger.error("⚠️ 火山引擎 App ID或Access Token未配置，将回退到ChatTTS")
                self.logger.info("请在 config/config.yaml 中配置 tts.volcengine.app_id 和 access_token")
                self.logger.info("注册地址: https://www.volcengine.com")
                # 回退到ChatTTS
                tts_config = self.config.get("chattts", {})
                try:
                    self.tts_engine = ChatTTSEngine(
                        device=tts_config.get('device', 'cpu'),
                        compile=tts_config.get('compile', False),
                        source=tts_config.get('source', 'huggingface'),
                        local_path=tts_config.get('local_path'),
                        temperature=tts_config.get('temperature', 0.3),
                        top_p=tts_config.get('top_p', 0.7),
                        top_k=tts_config.get('top_k', 20),
                        enable_refine=tts_config.get('enable_refine', True)
                    )
                except Exception as e:
                    self.logger.error(f"回退失败: {e}")
                    sys.exit(1)
            else:
                self.tts_engine = VolcengineTTS(
                    app_id=app_id,
                    access_token=access_token,
                    voice_type=tts_config.get('voice_type', 'zh_female_shuangkuaisisi_moon_bigtts'),
                    speed_ratio=tts_config.get('speed_ratio', 1.0),
                    volume_ratio=tts_config.get('volume_ratio', 1.0),
                    pitch_ratio=tts_config.get('pitch_ratio', 1.0),
                    emotion=tts_config.get('emotion', 'happy'),
                    audio_format=tts_config.get('audio_format', 'wav'),
                    sample_rate=tts_config.get('sample_rate', 24000),
                    timeout=tts_config.get('timeout', 30)
                )
                self.logger.info("🆚 使用火山引擎豆包TTS 2.0 (字节出品，成本更低)")
        
        elif tts_engine_type == "minimax":
            # 使用MiniMax TTS (推荐 - 全球榜首)
            tts_config = self.config.get_tts_config()
            api_key = tts_config.get('api_key', '')
            group_id = tts_config.get('group_id', '')
            
            if not api_key or not group_id:
                self.logger.error("⚠️ MiniMax API Key或Group ID未配置，将回退到ChatTTS")
                self.logger.info("请在 config/config.yaml 中配置 tts.minimax.api_key 和 group_id")
                self.logger.info("注册地址: https://www.minimaxi.com")
                # 回退到ChatTTS
                tts_config = self.config.get("chattts", {})
                try:
                    self.tts_engine = ChatTTSEngine(
                        device=tts_config.get('device', 'cpu'),
                        compile=tts_config.get('compile', False),
                        source=tts_config.get('source', 'huggingface'),
                        local_path=tts_config.get('local_path'),
                        temperature=tts_config.get('temperature', 0.3),
                        top_p=tts_config.get('top_p', 0.7),
                        top_k=tts_config.get('top_k', 20),
                        enable_refine=tts_config.get('enable_refine', True)
                    )
                except Exception as e:
                    self.logger.error(f"回退失败: {e}")
                    sys.exit(1)
            else:
                self.tts_engine = MiniMaxTTS(
                    api_key=api_key,
                    group_id=group_id,
                    voice_id=tts_config.get('voice_id', 'female-tianmei'),
                    speed=tts_config.get('speed', 1.0),
                    vol=tts_config.get('vol', 1.0),
                    pitch=tts_config.get('pitch', 0),
                    emotion=tts_config.get('emotion', 'happy'),
                    audio_sample_rate=tts_config.get('audio_sample_rate', 32000),
                    timeout=tts_config.get('timeout', 30)
                )
                self.logger.info("🏆 使用MiniMax TTS (全球榜首音质)")
        
        elif tts_engine_type == "chattts":
            # 使用ChatTTS (本地开源TTS)
            tts_config = self.config.get_tts_config()
            try:
                self.tts_engine = ChatTTSEngine(
                    device=tts_config.get('device', 'cpu'),
                    compile=tts_config.get('compile', False),
                    source=tts_config.get('source', 'huggingface'),
                    local_path=tts_config.get('local_path'),
                    temperature=tts_config.get('temperature', 0.3),
                    top_p=tts_config.get('top_p', 0.7),
                    top_k=tts_config.get('top_k', 20),
                    enable_refine=tts_config.get('enable_refine', True)
                )
            except ImportError:
                self.logger.error("⚠️ ChatTTS未安装，请运行: pip install ChatTTS torch torchaudio")
                self.logger.info("将回退到百度TTS")
                # 回退到百度TTS
                tts_config = self.config.get("baidu_tts", {})
                self.tts_engine = TTSEngine(
                    app_id=tts_config['app_id'],
                    api_key=tts_config['api_key'],
                    secret_key=tts_config['secret_key'],
                    per=tts_config.get('per', 4),
                    spd=tts_config.get('spd', 5),
                    pit=tts_config.get('pit', 5),
                    vol=tts_config.get('vol', 8),
                    aue=tts_config.get('aue', 6)
                )
        
        elif tts_engine_type == "fish_audio":
            # 使用Fish Audio TTS
            tts_config = self.config.get_tts_config()
            api_key = tts_config.get('api_key', '')
            
            if not api_key:
                self.logger.error("⚠️ Fish Audio API Key未配置，将回退到百度TTS")
                self.logger.info("请在 config/config.yaml 中配置 tts.fish_audio.api_key")
                # 回退到百度TTS
                tts_config = self.config.get("baidu_tts", {})
                self.tts_engine = TTSEngine(
                    app_id=tts_config['app_id'],
                    api_key=tts_config['api_key'],
                    secret_key=tts_config['secret_key'],
                    per=tts_config.get('per', 4),
                    spd=tts_config.get('spd', 5),
                    pit=tts_config.get('pit', 5),
                    vol=tts_config.get('vol', 8),
                    aue=tts_config.get('aue', 6)
                )
            else:
                self.tts_engine = FishAudioTTS(
                    api_key=api_key,
                    reference_id=tts_config.get('reference_id'),
                    api_url=tts_config.get('api_url', 'https://api.fish.audio/v1/tts'),
                    format=tts_config.get('format', 'wav'),
                    chunk_length=tts_config.get('chunk_length', 200),
                    timeout=tts_config.get('timeout', 30)
                )
        else:
            # 使用百度TTS (默认)
            tts_config = self.config.get("baidu_tts", {})
            self.tts_engine = TTSEngine(
                app_id=tts_config['app_id'],
                api_key=tts_config['api_key'],
                secret_key=tts_config['secret_key'],
                per=tts_config.get('per', 4),
                spd=tts_config.get('spd', 5),
                pit=tts_config.get('pit', 5),
                vol=tts_config.get('vol', 8),
                aue=tts_config.get('aue', 6)
            )
        
        self.logger.info("✓ TTS引擎初始化完成")

        # 5. 音频播放器
        self.audio_player = AudioPlayer()
        self.logger.info("✓ 音频播放器初始化完成")

        # 6. Live2D渲染器
        live2d_config = self.config.get_live2d_config()
        self.live2d_renderer = Live2DRenderer(
            model_path=live2d_config.get('model_path', './models/hiyori'),
            window_size=tuple(live2d_config.get('window_size', [1920, 1080])),
            fps=live2d_config.get('fps', 60),
            background_color=tuple(live2d_config.get('background_color', [0, 255, 0])),
            auto_open_browser=False  # 禁用自动打开浏览器，由 start_all.py 统一管理
        )
        if not self.live2d_renderer.initialize():
            self.logger.error("Live2D渲染器初始化失败")
        self.logger.info("✓ Live2D渲染器初始化完成")

        # 7. 弹幕监听器
        bilibili_config = self.config.get_bilibili_config()
        self.danmaku_listener = BilibiliDanmakuListener(
            room_id=bilibili_config['room_id'],
            on_message_callback=self._on_danmaku_received,
            max_reconnect=bilibili_config.get('max_reconnect', 5),
            reconnect_delay=bilibili_config.get('reconnect_delay', 5)
        )
        self.logger.info("✓ 弹幕监听器初始化完成")

        # 8. 消息处理器
        self.message_processor = MessageProcessor(
            message_queue=self.message_queue,
            process_callback=self._process_message,
            min_process_interval=1.0 / system_config.get('max_messages_per_second', 3),
            user_reply_interval=system_config.get('min_reply_interval', 3.0)
        )
        self.logger.info("✓ 消息处理器初始化完成")

        self.logger.info("=" * 60)
        self.logger.info("所有组件初始化完成!")
        self.logger.info("=" * 60)

    def _on_danmaku_received(self, message: DanmakuMessage):
        """
        弹幕接收回调
        
        Args:
            message: 弹幕消息
        """
        # 将消息加入队列
        self.message_queue.enqueue(message)
        
        # 输出详细日志
        self.logger.info(f"✓ 消息已加入队列 [队列长度: {self.message_queue.size()}]")

        # 更新状态
        self.controller.update_status(
            message_queue_length=self.message_queue.size()
        )

    def _process_message(self, message: DanmakuMessage):
        """
        处理单条消息
        
        Args:
            message: 弹幕消息
        """
        try:
            # 1. 敏感词过滤
            content = message.content
            if self.sensitive_filter:
                content = self.sensitive_filter.filter(content)

            # 显示正在回复的弹幕（重要：让直播观众知道回复的是哪条弹幕）
            self.logger.info(f"\n{'='*60}")
            self.logger.info(f"📩 收到弹幕: [{message.username}] {content}")
            self.logger.info(f"{'='*60}\n")

            # 2. 生成AI回复
            self.logger.info(f"🤖 AI思考中...")
            ai_response = self.ai_engine.generate_reply(content, message.username)
            
            # 显示回复内容（醒目标识正在回复谁）
            self.logger.info(f"\n{'🎙️'*20}")
            self.logger.info(f"💬 正在回复 @{message.username}: {ai_response.text}")
            self.logger.info(f"😊 情感: {ai_response.emotion.value}")
            self.logger.info(f"{'🎙️'*20}\n")

            # 3. 合成语音
            self.logger.info(f"合成语音中: {ai_response.text}")
            audio, lipsync_data = self.tts_engine.synthesize(ai_response.text)

            if audio is None:
                self.logger.error("语音合成失败")
                return

            # 4. 设置Live2D情感
            self.live2d_renderer.set_emotion(ai_response.emotion)

            # 5. 播放语音并同步口型
            self.controller.update_status(is_speaking=True)
            self.logger.info(f"🎤 开始播放语音 (口型帧数: {len(lipsync_data)})")

            def on_lipsync_frame(lipsync):
                """口型同步回调"""
                self.live2d_renderer.update_mouth(lipsync)
                # 输出调试信息（每10帧输出一次，避免刷屏）
                if hasattr(on_lipsync_frame, 'frame_count'):
                    on_lipsync_frame.frame_count += 1
                else:
                    on_lipsync_frame.frame_count = 0
                
                if on_lipsync_frame.frame_count % 10 == 0:
                    self.logger.debug(f"   口型同步: 张开度={lipsync.mouth_open:.2f} 音量={lipsync.volume:.2f}")

            # 在单独线程中播放音频
            def play_audio_thread():
                self.audio_player.play_with_lipsync(
                    audio,
                    lipsync_data,
                    on_frame_callback=on_lipsync_frame
                )
                # 播放完成后重置嘴巴
                self.logger.info("✓ 语音播放完成，重置口型")
                self.live2d_renderer.reset_mouth()
                self.controller.update_status(is_speaking=False)

            threading.Thread(target=play_audio_thread, daemon=True).start()

            # 6. 更新统计
            self.controller.update_status(
                total_messages_processed=self.controller.status.total_messages_processed + 1
            )

            self.logger.info(f"✓ 消息处理完成: {ai_response.text}")

        except Exception as e:
            self.logger.error(f"处理消息失败: {e}")
            import traceback
            self.logger.error(traceback.format_exc())

    def start(self):
        """启动系统"""
        if self.is_running:
            self.logger.warning("系统已在运行")
            return

        self.is_running = True
        self.logger.info("正在启动AI虚拟主播系统...")

        # 更新状态
        self.controller.update_status(is_connected=False)

        # 1. 启动消息处理器
        self.message_processor.start()

        # 2. 启动Live2D渲染(在单独线程中)
        self.controller.start_thread(
            name="live2d_renderer",
            target=self.live2d_renderer.start
        )

        # 3. 启动弹幕监听(异步)
        self.controller.start_thread(
            name="danmaku_listener",
            target=self._start_danmaku_listener_sync
        )

        self.logger.info("=" * 60)
        self.logger.info("✓ AI虚拟主播系统启动成功!")
        self.logger.info("=" * 60)

        # 注册信号处理
        signal.signal(signal.SIGINT, self._signal_handler)
        signal.signal(signal.SIGTERM, self._signal_handler)

        # 保持主线程运行
        self._main_loop()

    def _start_danmaku_listener_sync(self):
        """同步启动弹幕监听器(在单独线程中运行异步代码)"""
        try:
            asyncio.run(self.danmaku_listener.start())
        except Exception as e:
            self.logger.error(f"弹幕监听器异常: {e}")

    def _main_loop(self):
        """主循环"""
        try:
            while self.is_running:
                # 定期输出状态信息
                import time
                time.sleep(10)

                stats = self.message_queue.get_stats()
                status = self.controller.get_status()

                self.logger.info(
                    f"状态: 队列={stats['size']}/{self.message_queue.max_size} | "
                    f"已处理={status.total_messages_processed} | "
                    f"运行时长={status.uptime}"
                )

        except KeyboardInterrupt:
            self.logger.info("接收到中断信号")
            self.stop()

    def _signal_handler(self, signum, frame):
        """信号处理器"""
        self.logger.info(f"接收到信号: {signum}")
        self.stop()

    def stop(self):
        """停止系统"""
        if not self.is_running:
            return

        self.logger.info("正在停止AI虚拟主播系统...")
        self.is_running = False

        # 1. 停止消息处理器
        if self.message_processor:
            self.message_processor.stop()

        # 2. 停止弹幕监听
        if self.danmaku_listener:
            asyncio.run(self.danmaku_listener.stop())

        # 3. 停止Live2D渲染
        if self.live2d_renderer:
            self.live2d_renderer.stop()

        # 4. 清理TTS临时文件
        if self.tts_engine:
            self.logger.info("清理TTS临时文件...")
            self.tts_engine.cleanup_temp_files()

        # 5. 停止所有线程
        self.controller.stop_all_threads()

        self.logger.info("=" * 60)
        self.logger.info("✓ AI虚拟主播系统已停止")
        self.logger.info("=" * 60)


def main():
    """主入口"""
    # 创建系统实例
    system = AIVTuberSystem()

    # 启动系统
    system.start()


if __name__ == "__main__":
    main()
